package com.sghd.football.robot.core;

import com.sghd.common.console.ConsoleBean;
import com.sghd.common.console.ConsoleCommand;
import com.sghd.common.socket.client.Client;
import com.sghd.common.socket.client.ClientFactory;
import com.sghd.common.socket.core.Message;
import com.sghd.football.module.game.facade.model.GameResult;
import com.sghd.football.robot.action.OpAction;
import com.sghd.football.utils.SocketEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

/**
 * @author wch
 * @date 2018-07-06 12:08
 * @desc 控制器
 **/
@Component
@ConsoleBean
public class Controller {
    private Logger logger = LoggerFactory.getLogger(Controller.class);
    @Autowired
    private ClientFactory clientFactory;
    private ConcurrentMap<Long, Robot> robots = new ConcurrentHashMap<>();
    /**任务高度*/
    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(100);

    @ConsoleCommand(name = "run", description = "开始测试")
    public void run(int times) {
        int count = 100;
        long base = 10000003;
        for (int i = 0; i < count; i++) {
            long robotId = base + i;
            int finalI = i;
            executor.submit(() -> {
                try {
                    Client client = clientFactory.getClient("127.0.0.1", 6012);
                    Robot robot = Robot.valueOf(robotId, "ROBOT[" + finalI + "]", client, this, times);
                    robots.put(robotId, robot);
                    robot.action();
                } catch (Exception e) {
                    logger.error("机器人[{}]发生故障了!", robotId);
                }
            });
        }
    }

    @ConsoleCommand(name = "close", description = "停止测试")
    public void stop() {
        for (Robot robot : robots.values()) {
            if (robot.isAlive()) {
                synchronized (robot) {
                    robot.setClose(true);
                }
            }
        }
        for (Robot robot : robots.values()) {
            robot.getClient().close();
        }
    }

    @ConsoleCommand(name = "show")
    public void calc() {
        try {
            List<Long> ids = new ArrayList<>(robots.keySet());
            Collections.sort(ids);

            int low = 0;
            int win = 0;
            int cen = 0;//不输不赢
            BigDecimal free = new BigDecimal("0");
            BigDecimal mini = new BigDecimal("0");
            BigDecimal reward = new BigDecimal("0");
            BigDecimal yinqian = new BigDecimal("0");
            BigDecimal freewin = new BigDecimal("0");
            long sysChange = 0;
            long con = 0;
            int op = 0;
            for (Long robotId : ids) {
                Robot robot = robots.get(robotId);
                if (!robot.isAlive()) {
                    continue;
                }
                synchronized (robot) {
                    op += robot.getOp();
                    con++;
                    logger.debug("机器人[{}]->{}", robot.getRobotId(), robot.getName());
                    logger.debug("总旋转次数->{}", robot.getOp());
                    logger.debug("背包金币->{}", robot.getMoney());
                    //中免费概率
                    BigDecimal decimal = BigDecimal.valueOf(robot.getFree()).divide(BigDecimal.valueOf(robot.getOp()), 6, BigDecimal.ROUND_HALF_UP);
                    free = free.add(decimal);
                    logger.debug("中免费的概率->{}", decimal.toString());

                    //中小游戏概率
                    decimal = BigDecimal.valueOf(robot.getBounds()).divide(BigDecimal.valueOf(robot.getOp()), 6, BigDecimal.ROUND_HALF_UP);
                    mini = mini.add(decimal);
                    logger.debug("中小游戏的概率->{}", decimal.toString());

                    //中奖概率
                    decimal = BigDecimal.valueOf(robot.getRewards()).divide(BigDecimal.valueOf(robot.getOp()), 6, BigDecimal.ROUND_HALF_UP);
                    reward = reward.add(decimal);
                    logger.debug("中奖概率->{}", decimal.toString());

                    //赢钱(大奖)概率（中奖金额大于下注总金额）
                    decimal = BigDecimal.valueOf(robot.getBigWin()).divide(BigDecimal.valueOf(robot.getOp()), 6, BigDecimal.ROUND_HALF_UP);
                    yinqian = yinqian.add(decimal);
                    logger.debug("赢钱(大奖)概率->{}", decimal.toString());

                    //免费游戏中的中奖概率
                    if (robot.getFreeCount() != 0) {
                        decimal = BigDecimal.valueOf(robot.getFreeWin()).divide(BigDecimal.valueOf(robot.getFreeCount()), 6, BigDecimal.ROUND_HALF_UP);
                        freewin = freewin.add(decimal);
                        logger.debug("免费游戏中奖概率->{}", decimal.toString());
                    } else {
                        logger.debug("免费游戏中奖概率->{}", 0.0);
                    }
                    if (robot.getMoney() > 0) {
                        win++;
                    } else if (robot.getMoney() < 0) {
                        low++;
                    } else {
                        cen++;
                    }
                    sysChange += robot.getMoney();
                    System.out.println();
                }
            }
            System.out.println("-----------------------------------------------分界线-------------------------------------------------------");
            logger.debug("旋转[{}]次 ->  汇总", op / con);
            logger.debug("中免费的概率(平均)-->:{}", free.divide(BigDecimal.valueOf(con), 6, BigDecimal.ROUND_HALF_UP));
            logger.debug("中小游戏的概率(平均)-->:{}", mini.divide(BigDecimal.valueOf(con), 6, BigDecimal.ROUND_HALF_UP));
            logger.debug("中奖的概率(平均)-->:{}", reward.divide(BigDecimal.valueOf(con), 6, BigDecimal.ROUND_HALF_UP));
            logger.debug("赢钱的概率(平均)-->:{}", yinqian.divide(BigDecimal.valueOf(con), 6, BigDecimal.ROUND_HALF_UP));
            logger.debug("免费中中奖的概率(平均)-->:{}", freewin.divide(BigDecimal.valueOf(con), 6, BigDecimal.ROUND_HALF_UP));
            logger.debug("总[{}]个玩家--> 输：[{}]，赢：[{}]，不输不赢：[{}]", robots.size(), low, win, cen);
            logger.debug("所有玩家金币总和：" + sysChange);
        } catch (Exception e) {
            logger.error("统计机器人数据发生未知错误！", e);
        }
    }

    @ConsoleCommand(name = "clean", description = "清理数据")
    public void clean() {
        robots.clear();
    }

    public void doEnter(long robotId) {
        Robot robot = robots.get(robotId);
        Map<String, Object> enter = new HashMap<>();
        enter.put("configId", 0);
        enter.put("gameId", 32);
        robot.getClient().send(Message.valueOf(SocketEnum.JOIN_ROOM, enter));
    }

    //添加定时任务
    public void addWork(Runnable runnable, int delay) {
        executor.schedule(runnable, delay, TimeUnit.MILLISECONDS);
    }

    public void initDesk(long robotId, String name) {
        Robot robot = robots.get(robotId);
        robot.setAlive(true);
        robot.setNext(new OpAction());//开始旋转
        robot.setName(robot.getName()+"->"+name);
    }

    /**收到服务器结算完成*/
    public void complete(long robotId, Integer type) {
        Robot robot = robots.get(robotId);
        if (robot.getOp() >= robot.getTimes()) {
            robot.setClose(true);
            robot.getClient().close();
            return;
        }
        if (robot.isCurBounds()) {
            if (type == 1) {
                robot.setNext(new OpAction());//继续旋转
            }
        } else {
            robot.setNext(new OpAction());//继续旋转
        }
    }

    /**旋转结束 */
    public void operator(long robotId, GameResult result) {
        Robot robot = robots.get(robotId);
        robot.setGameResult(result);
        robot.setMoney(result.getCurMoney());
        robot.setOp(robot.getOp() + 1);//旋转次数+1
        if (result.getResult().isBounds()) {
            robot.setBounds(robot.getBounds() + 1);//获得一次小游戏+1
            robot.setCurBounds(true);
        } else {
            robot.setCurBounds(false);
        }
        if (result.getNexFreeFlag() == 10) {
            robot.setFree(robot.getFree() + 1);//获得免费旋转+1
        }
        if (result.getResult().isCurrentFree()) {//当前是免费中
            robot.setFreeCount(robot.getFreeCount() + 1);
            if (result.getResult().getGameResult().size() > 0) {
                robot.setFreeWin(robot.getFreeWin() + 1);//中奖次数+1
            }
        }
        if (result.getResult().getGameResult().size() > 0) {
            robot.setRewards(robot.getRewards() + 1);//中奖次数+1
        }
        long totalBet = OpAction.bets[robot.getLastBet()] * 30;//总下注
        if (result.getResult().getTotalFen() > totalBet) {//赢钱金额大于总下注
            robot.setBigWin(robot.getBigWin() + 1);
        }
    }

    public void mini(long robotId, long money) {
        Robot robot = robots.get(robotId);
        robot.setMoney(robot.getMoney() + money);
    }
}
